library(tidyverse)
── Attaching core tidyverse packages ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.2 ✔ readr 2.1.4
✔ forcats 1.0.0 ✔ stringr 1.5.0
✔ ggplot2 3.4.2 ✔ tibble 3.2.1
✔ lubridate 1.9.2 ✔ tidyr 1.3.0
✔ purrr 1.0.1 ── Conflicts ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(janitor)
Attaching package: ‘janitor’
The following objects are masked from ‘package:stats’:
chisq.test, fisher.test
steam <- read_csv("raw_data/steam_checkpoint.csv")
Rows: 26564 Columns: 22── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (8): name, developer, publisher, multiplayer, categories, genres, steamspy_tags, owners
dbl (8): appid, required_age, achievements, positive_ratings, negative_ratings, average_playtime, median_playtime, price
lgl (5): free_to_play, virtual_reality_support, windows_support, mac_support, linux_support
date (1): release_date
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Where was i?
games_pre_cleaned <- read_csv("raw_data/Cleaned Data 2 GVGS&R.csv")
Rows: 6894 Columns: 15── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (5): Name, Genre, Publisher, Developer, Rating
dbl (10): Year_of_Release, NA_Sales, EU_Sales, JP_Sales, Other_Sales, Global_Sales, Critic_Score, Critic_Count, User_Score, User_Count
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
games_pre_cleaned
How dare you do the work for me
games_raw <- read_csv("raw_data/Raw Data GVGS&R.csv")
Rows: 16719 Columns: 16── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (8): Name, Platform, Year_of_Release, Genre, Publisher, User_Score, Developer, Rating
dbl (8): NA_Sales, EU_Sales, JP_Sales, Other_Sales, Global_Sales, Critic_Score, Critic_Count, User_Count
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
games_raw %>%
filter(Name == "Minecraft")
Why does everyone have the same dataset
back to steam i guess
steam
steam %>%
distinct(genres)
Already have F2P covered by another column, so we can drop that in
genres
steam %>%
mutate(genres = str_remove_all(genres, "Free to Play")) %>%
filter(free_to_play == TRUE)
Is this worth doing? Duplicated info doesn’t hurt i suppose - leave
it for now
single player?
steam <- steam %>%
mutate(singleplayer = case_when(
str_detect(categories, "Single-player") ~ TRUE,
str_detect(steamspy_tags, "Singleplayer") ~ TRUE,
TRUE ~ FALSE
),.before = multiplayer)
steam %>%
filter(free_to_play == TRUE)
steam
# adding column to simplify ratings
steam <- steam %>%
mutate(total_reviews = positive_ratings + negative_ratings) %>%
arrange(desc(total_reviews)) %>%
mutate(percent_positive_reviews = positive_ratings / total_reviews) %>%
mutate(general_rating = case_when(
total_reviews > 1000 & percent_positive_reviews >= 0.95 ~ "Extremely Positive",
total_reviews > 1000 & percent_positive_reviews >= 0.75 ~ "Positive",
total_reviews > 1000 & percent_positive_reviews >= 0.55 ~ "Mostly Positive",
total_reviews > 1000 & percent_positive_reviews >= 0.50 ~ "Mixed" ,
total_reviews > 1000 & percent_positive_reviews >= 0.35 ~ " Mostly Negative",
total_reviews > 1000 & percent_positive_reviews >= 0.15 ~ "Negative",
total_reviews > 1000 & percent_positive_reviews < 0.15 ~ "Extremely Negative",
positive_ratings == 0 ~ "No Positive Reviews",
negative_ratings == 0 ~ "No Negative Reviews",
positive_ratings & negative_ratings == 0 ~ "No Reviews",
total_reviews < 1000 ~ "Not Enough Reviews",
TRUE ~ "No Data"
),.before = positive_ratings) %>%
select(-percent_positive_reviews)
backloggd <- read_csv("clean_data/backloggd_clean.csv")
Rows: 1115 Columns: 15── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (9): title, team, genre_tag, genre_tag_2, genre_tag_3, genre_tag_4, genre_tag_5, genre_tag_6, genre_tag_7
dbl (5): years_since_release, rating, number_of_reviews, wishlist, plays
date (1): release_date
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
backloggd
games_raw <- games_raw %>%
clean_names()
# Platform isn't a genre - correcting
games_raw <- games_raw %>%
mutate(genre = case_when(
genre == "Platform" ~ "Platformer",
TRUE ~ genre
))
nintendo_published <- games_raw %>%
filter(publisher == "Nintendo")
genre_publisher_sales <- games_raw %>%
group_by(publisher, genre) %>%
summarise(sum(global_sales)) %>%
arrange(desc(`sum(global_sales)`))
`summarise()` has grouped output by 'publisher'. You can override using the `.groups` argument.
write_csv(genre_publisher_sales, "clean_data/genre_by_publisher.csv")
genre_publisher_sales %>%
filter(publisher == "From Software")
games_raw %>%
distinct(rating)
# clarifying that the rating is for ESRP - the american system
games_raw <- games_raw %>%
rename("esrp" = "rating")
# Adding PEGI equivalent
games_raw <- games_raw %>%
mutate(pegi_equivalent = case_when(
esrp == "EC" ~ "3",
esrp == "E" ~ "7",
esrp == "E10+" ~ "12",
esrp == "T" ~ "16",
esrp == "M" ~ "18",
esrp == "AO" ~ "18",
esrp == "K-A" ~ "7",
esrp == "RP" ~ "No Rating",
TRUE ~ "No Rating Found"
))
total_sales_by_genre <- games_raw %>%
group_by(genre) %>%
summarise(sum(global_sales)) %>%
rename("total_sales" = "sum(global_sales)") %>%
arrange(desc(total_sales))
total_sales_by_genre <- total_sales_by_genre %>%
drop_na()
games_raw
breakdown_sales_by_genre <- games_raw %>%
group_by(genre) %>%
summarise(sum(na_sales), sum(eu_sales), sum(jp_sales), sum(other_sales)) %>%
rename("total_na_sales"= "sum(na_sales)", "total_eu_sales" = "sum(eu_sales)", "total_jp_sales" = "sum(jp_sales)", "total_other_sales" = "sum(other_sales)")
total_sales_by_genre # this seems to have some rounding differences compared to breakdown, so i'll retire this one
how does the sales for the top 3 genres look in each region?
breakdown_sales_by_genre <- breakdown_sales_by_genre %>%
group_by(genre) %>%
mutate(total_sales = sum(total_na_sales + total_eu_sales + total_jp_sales + total_other_sales)) %>%
drop_na()
breakdown_sales_by_genre %>%
filter(genre %in% c("Action", "Sports", "Shooter")) %>%
ggplot(aes(x = total_sales, y = genre))+
geom_col() +
geom_col(aes(x = total_na_sales), fill = "green")+
geom_col(aes(x = total_eu_sales), fill = "red") +
geom_col(aes(x = total_jp_sales), fill = "blue")

# this looks shit
What about trends? How did each genres sales adjust every 5 or so
years?
games_raw %>%
filter(year_of_release == "2016")
games_raw %>%
mutate(year_of_release = as.integer(year_of_release)) %>%
distinct(year_of_release) %>%
arrange(year_of_release)
Warning: There was 1 warning in `mutate()`.
ℹ In argument: `year_of_release = as.integer(year_of_release)`.
Caused by warning:
! NAs introduced by coercion
sales_2019 <- read_csv("raw_data/sales-2019.csv")
Rows: 55792 Columns: 23── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (10): Name, basename, Genre, ESRB_Rating, Platform, Publisher, Developer, Last_Update, url, img_url
dbl (12): Rank, Critic_Score, User_Score, Total_Shipped, Global_Sales, NA_Sales, PAL_Sales, JP_Sales, Other_Sales, Year, status, Vgchartzscore
lgl (1): VGChartz_Score
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
sales_2019 %>%
distinct(Year) %>%
arrange(desc(Year))
sales_2019 %>%
filter(Year == "2019") %>%
select(Name, Year, Platform)
# data for 2020 is total nonsense. Some information in 2019 is incorrect.
Going off the fact that there is the majority of usable information
i am able to get is from 2019 or before, we’re just going to pretend
we’re living in an
alternative 2019
As such, I am dropping all data from 2020 in this dataset
sales_2019 <- sales_2019 %>%
filter(Year != "2020")
Looking at backloggd again
backloggd
# creating a range_rating column to reduce noise when it comes to plotting results
backlogged <- backloggd %>%
mutate(rating_range = case_when(
rating < 5 & rating >= 4 ~ "4+",
rating < 4 & rating >= 3 ~ "3 to 4",
rating < 3 & rating >= 2 ~ "2 to 3",
rating < 2 & rating >= 1 ~ "1 to 2",
rating < 1 ~ ">1",
TRUE ~ "No rating"
))
DIFFICULTIES WITH THE DATA
After having little success attempting to get a more up to date data
set, i’ve decided to stick with what I already have - Given more time, i
would have liked to have run the steam/steam spy script to scrape all
the steam data, but unfortunately i couldn’t commit 3 days to it. There
doesn’t seem to be much in the way of modern sales data, with most
companies not releasing figures unless its to do with a milestone.
Genres are quite vague - While it would be nice to have tags like “Open
World”, “Rouge-like/lite”, we instead mostly have “Action” “Adventure”,
“Indie”, which are not hugely descriptive. This might make recommending
a genre to work on harder
DAY 3
sales_2019 %>%
summary()
Rank Name basename Genre ESRB_Rating Platform Publisher Developer VGChartz_Score Critic_Score
Min. : 1 Length:54482 Length:54482 Length:54482 Length:54482 Length:54482 Length:54482 Length:54482 Mode:logical Min. : 1.00
1st Qu.:13638 Class :character Class :character Class :character Class :character Class :character Class :character Class :character NA's:54482 1st Qu.: 6.40
Median :27421 Mode :character Mode :character Mode :character Mode :character Mode :character Mode :character Mode :character Median : 7.50
Mean :27465 Mean : 7.21
3rd Qu.:41202 3rd Qu.: 8.30
Max. :55791 Max. :10.00
NA's :47952
User_Score Total_Shipped Global_Sales NA_Sales PAL_Sales JP_Sales Other_Sales Year Last_Update url status
Min. : 2.00 Min. : 0.03 Min. : 0.00 Min. :0.00 Min. :0.00 Min. :0.00 Min. :0.00 Min. :1970 Length:54482 Length:54482 Min. :1
1st Qu.: 7.80 1st Qu.: 0.20 1st Qu.: 0.03 1st Qu.:0.05 1st Qu.:0.01 1st Qu.:0.02 1st Qu.:0.00 1st Qu.:2000 Class :character Class :character 1st Qu.:1
Median : 8.50 Median : 0.59 Median : 0.12 Median :0.12 Median :0.04 Median :0.05 Median :0.01 Median :2008 Mode :character Mode :character Median :1
Mean : 8.27 Mean : 1.89 Mean : 0.37 Mean :0.28 Mean :0.16 Mean :0.11 Mean :0.04 Mean :2006 Mean :1
3rd Qu.: 9.20 3rd Qu.: 1.80 3rd Qu.: 0.36 3rd Qu.:0.29 3rd Qu.:0.14 3rd Qu.:0.12 3rd Qu.:0.04 3rd Qu.:2011 3rd Qu.:1
Max. :10.00 Max. :82.86 Max. :20.32 Max. :9.76 Max. :9.85 Max. :2.69 Max. :3.12 Max. :2019 Max. :1
NA's :54154 NA's :52661 NA's :35132 NA's :41528 NA's :41334 NA's :47458 NA's :39005
Vgchartzscore img_url
Min. :2.60 Length:54482
1st Qu.:6.90 Class :character
Median :7.90 Mode :character
Mean :7.49
3rd Qu.:8.50
Max. :9.60
NA's :53726
All of the VGchartz scores are empty, so it can go. Also, same as
above, there’s no such genre as Platform
1970 is nonsense. dropping entire year
sales_2019 %>%
group_by(five_year_period) %>%
count(genre) %>%
slice_max(n = 2, n) %>%
ggplot(aes(x = five_year_period, y = n, fill = genre)) +
geom_col(colour = "black") +
labs(
title = "Most Common Genres Over Time",
subtitle = "Shown over 5 year intervals",
caption = "From 2019 games sales data"
) +
scale_fill_manual(values = c(
"Platformer" = "#04E762",
"Action" = "#DC0073",
"Sports" = "#008BF8",
"Misc" = "#f5b700",
"Shooter" = "#390099"
)) +
theme_light() +
theme(axis.text.x = element_text(angle = 25, hjust = 0.5, size = 9, face = "bold", vjust = 0.8)) +
theme(axis.line = element_line(colour = "black"))+
theme(axis.text.y = element_text(size = 9, face = "bold")) +
xlab("Interval") +
ylab("Number of Games in the genre released") +
theme(axis.title.x = element_text(face = "italic", size = 10)) +
theme(axis.title.y = element_text(face = "italic", size = 10)) +
theme(plot.caption = element_text(size = 7, hjust = 1.25)) +
labs(fill = "Genre")

# Misc isnt very descriptive or helpful - in terms of recommending making something to someone it means essentially "try anything"
# PLOT SHOWING MOST COMMON GENRE OF GAMES - NOT NECESSARILY BEST SELLING
sales_2019 %>%
group_by(five_year_period) %>%
filter(genre != "Misc") %>%
count(genre) %>%
slice_max(n = 2, n) %>%
ggplot(aes(x = five_year_period, y = n, fill = genre)) +
geom_col(colour = "black") +
labs(
title = "Most Common Genres Over Time",
subtitle = "Shown over 5 year intervals - Excluding 'Misc' genre",
caption = "From 2019 game sales data"
) +
scale_fill_manual(values = c(
"Platformer" = "#04E762",
"Action" = "#DC0073",
"Sports" = "#008BF8",
# "Misc" = "#f5b700",
"Shooter" = "#390099",
"Adventure" = "#8ac926",
"Role-Playing" = "#ff6b35"
)) +
theme_light() +
theme(axis.text.x = element_text(angle = 25, hjust = 0.5, size = 9, face = "bold", vjust = 0.8)) +
theme(axis.line = element_line(colour = "black"))+
theme(axis.text.y = element_text(size = 9, face = "bold")) +
xlab("Interval") +
ylab("Number of Games in the genre released") +
theme(axis.title.x = element_text(face = "italic", size = 10)) +
theme(axis.title.y = element_text(face = "italic", size = 10)) +
theme(plot.caption = element_text(size = 7, hjust = 1.25)) +
labs(fill = "Genre")

NA
This is slightly concerning - a lot of these titles could easily have
a genre that isn’t the cure-all “Misc” - Include both graphs - one with
misc, one excluding it
What about a similar plot for steam games?
steam_years <- steam_years %>%
separate(col = genres, sep = ";", into = paste0("Genre", seq_len(max(nchar(.$genres))))) %>% # this is absolutely horrendous, but it gets me all the genres into separate columns so whatever
select(-Genre14:-Genre180) %>%
pivot_longer(cols = Genre1:Genre13, names_to = "genres") %>%
drop_na(value) %>% # ok now we can make the year intervals and group them to find what genres were popular
mutate(year_range = case_when(
release_year <= 2019 & release_year >= 2016 ~ "2016 - 2019",
release_year <= 2015 & release_year >= 2012 ~ "2012 - 2015",
release_year <= 2011 & release_year >= 2009 ~ "2009 - 2011",
release_year <= 2008 & release_year >= 2005 ~ "2005 - 2008",
release_year <= 2004 & release_year>= 2000 ~ "2000 - 2004",
release_year < 2001 ~ "Before 2000",
TRUE ~ "this shouldnt appear"
),.after = release_year)
Warning: Expected 180 pieces. Missing pieces filled with `NA` in 26564 rows [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...].

steam_years %>%
filter(release_year >= 2009) %>%
group_by(release_year) %>%
count(value) %>%
slice_max(n = 2, n) %>%
arrange(desc(n)) %>%
ggplot(aes(x = release_year, y = n, fill = value)) +
geom_col(colour = "black") +
labs(
title = "Most Common Genres Over Time",
subtitle = "Shown year by year from 2009 until May 2019",
caption = "From 2019 Steam/Steam Spy data"
) +
scale_fill_manual(values = c(
"Indie" = "#04E762",
"Action" = "#DC0073",
"Casual" = "#008BF8",
"Adventure" = "#f5b700"
)) +
theme_light() +
theme(axis.text.x = element_text(angle = 25, hjust = 0.5, size = 9, face = "bold", vjust = 0.8)) +
theme(axis.line = element_line(colour = "black"))+
theme(axis.text.y = element_text(size = 9, face = "bold")) +
xlab("Interval") +
ylab("Number of Games in the genre released") +
theme(axis.title.x = element_text(face = "italic", size = 10)) +
theme(axis.title.y = element_text(face = "italic", size = 10)) +
theme(plot.caption = element_text(size = 7, hjust = 1.25)) +
scale_x_continuous(breaks = c(2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019)) +
labs(fill = "Genre")

backloggd_genres %>%
pivot_longer(cols = genre_tag:genre_tag_7, names_to = "list", values_to = "genre") %>%
drop_na(genre)
Error in pivot_longer(., cols = genre_tag:genre_tag_7, names_to = "list", :
object 'backloggd_genres' not found

We have established that Indie, Action and Adventure games seem to
be the most popular - But what examples of these are there?
LS0tDQp0aXRsZTogIkRBWSAyIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoamFuaXRvcikNCg0Kc3RlYW0gPC0gcmVhZF9jc3YoInJhd19kYXRhL3N0ZWFtX2NoZWNrcG9pbnQuY3N2IikNCmBgYA0KDQpXaGVyZSB3YXMgaT8NCg0KYGBge3J9DQpnYW1lc19wcmVfY2xlYW5lZCA8LSByZWFkX2NzdigicmF3X2RhdGEvQ2xlYW5lZCBEYXRhIDIgR1ZHUyZSLmNzdiIpDQpgYGANCg0KYGBge3J9DQpnYW1lc19wcmVfY2xlYW5lZA0KYGBgDQpIb3cgZGFyZSB5b3UgZG8gdGhlIHdvcmsgZm9yIG1lDQoNCmBgYHtyfQ0KZ2FtZXNfcmF3IDwtIHJlYWRfY3N2KCJyYXdfZGF0YS9SYXcgRGF0YSBHVkdTJlIuY3N2IikNCmBgYA0KDQpgYGB7cn0NCmdhbWVzX3JhdyAlPiUgDQogIGZpbHRlcihOYW1lID09ICJNaW5lY3JhZnQiKQ0KYGBgDQpXaHkgZG9lcyBldmVyeW9uZSBoYXZlIHRoZSBzYW1lIGRhdGFzZXQNCg0KYmFjayB0byBzdGVhbSBpIGd1ZXNzDQoNCmBgYHtyfQ0Kc3RlYW0NCmBgYA0KDQpgYGB7cn0NCnN0ZWFtICU+JSANCiAgZGlzdGluY3QoZ2VucmVzKQ0KYGBgDQoNCkFscmVhZHkgaGF2ZSBGMlAgY292ZXJlZCBieSBhbm90aGVyIGNvbHVtbiwgc28gd2UgY2FuIGRyb3AgdGhhdCBpbiBnZW5yZXMNCg0KYGBge3J9DQpzdGVhbSAlPiUgDQogIG11dGF0ZShnZW5yZXMgPSBzdHJfcmVtb3ZlX2FsbChnZW5yZXMsICJGcmVlIHRvIFBsYXkiKSkgJT4lIA0KICBmaWx0ZXIoZnJlZV90b19wbGF5ID09IFRSVUUpDQpgYGANCg0KSXMgdGhpcyB3b3J0aCBkb2luZz8NCkR1cGxpY2F0ZWQgaW5mbyBkb2Vzbid0IGh1cnQgaSBzdXBwb3NlIC0gbGVhdmUgaXQgZm9yIG5vdw0KDQpzaW5nbGUgcGxheWVyPw0KDQpgYGB7cn0NCnN0ZWFtIDwtIHN0ZWFtICU+JSANCiAgbXV0YXRlKHNpbmdsZXBsYXllciA9IGNhc2Vfd2hlbigNCiAgICBzdHJfZGV0ZWN0KGNhdGVnb3JpZXMsICJTaW5nbGUtcGxheWVyIikgfiBUUlVFLA0KICAgIHN0cl9kZXRlY3Qoc3RlYW1zcHlfdGFncywgIlNpbmdsZXBsYXllciIpIH4gVFJVRSwNCiAgICBUUlVFIH4gRkFMU0UNCiAgKSwuYmVmb3JlID0gbXVsdGlwbGF5ZXIpDQpgYGANCg0KYGBge3J9DQpzdGVhbSAlPiUgDQogIGZpbHRlcihmcmVlX3RvX3BsYXkgPT0gVFJVRSkgDQpgYGANCmBgYHtyfQ0Kc3RlYW0NCmBgYA0KYGBge3J9DQojIGFkZGluZyBjb2x1bW4gdG8gc2ltcGxpZnkgcmF0aW5ncyANCnN0ZWFtIDwtIHN0ZWFtICU+JSANCiAgbXV0YXRlKHRvdGFsX3Jldmlld3MgPSBwb3NpdGl2ZV9yYXRpbmdzICsgIG5lZ2F0aXZlX3JhdGluZ3MpICU+JSANCiAgYXJyYW5nZShkZXNjKHRvdGFsX3Jldmlld3MpKSAlPiUgDQogIG11dGF0ZShwZXJjZW50X3Bvc2l0aXZlX3Jldmlld3MgPSBwb3NpdGl2ZV9yYXRpbmdzIC8gdG90YWxfcmV2aWV3cykgJT4lIA0KICBtdXRhdGUoZ2VuZXJhbF9yYXRpbmcgPSBjYXNlX3doZW4oDQogICAgdG90YWxfcmV2aWV3cyA+IDEwMDAgJiBwZXJjZW50X3Bvc2l0aXZlX3Jldmlld3MgPj0gMC45NSB+ICJFeHRyZW1lbHkgUG9zaXRpdmUiLA0KICAgIHRvdGFsX3Jldmlld3MgPiAxMDAwICYgcGVyY2VudF9wb3NpdGl2ZV9yZXZpZXdzID49IDAuNzUgfiAiUG9zaXRpdmUiLA0KICAgIHRvdGFsX3Jldmlld3MgPiAxMDAwICYgcGVyY2VudF9wb3NpdGl2ZV9yZXZpZXdzID49IDAuNTUgfiAiTW9zdGx5IFBvc2l0aXZlIiwNCiAgICB0b3RhbF9yZXZpZXdzID4gMTAwMCAmIHBlcmNlbnRfcG9zaXRpdmVfcmV2aWV3cyA+PSAwLjUwIH4gIk1peGVkIiAsDQogICAgdG90YWxfcmV2aWV3cyA+IDEwMDAgJiBwZXJjZW50X3Bvc2l0aXZlX3Jldmlld3MgPj0gMC4zNSB+ICIgTW9zdGx5IE5lZ2F0aXZlIiwNCiAgICB0b3RhbF9yZXZpZXdzID4gMTAwMCAmIHBlcmNlbnRfcG9zaXRpdmVfcmV2aWV3cyA+PSAwLjE1IH4gIk5lZ2F0aXZlIiwNCiAgICB0b3RhbF9yZXZpZXdzID4gMTAwMCAmIHBlcmNlbnRfcG9zaXRpdmVfcmV2aWV3cyA8IDAuMTUgfiAiRXh0cmVtZWx5IE5lZ2F0aXZlIiwNCiAgICBwb3NpdGl2ZV9yYXRpbmdzID09IDAgfiAiTm8gUG9zaXRpdmUgUmV2aWV3cyIsDQogICAgbmVnYXRpdmVfcmF0aW5ncyA9PSAwIH4gIk5vIE5lZ2F0aXZlIFJldmlld3MiLA0KICAgIHBvc2l0aXZlX3JhdGluZ3MgJiBuZWdhdGl2ZV9yYXRpbmdzID09IDAgfiAiTm8gUmV2aWV3cyIsDQogICAgdG90YWxfcmV2aWV3cyA8IDEwMDAgfiAiTm90IEVub3VnaCBSZXZpZXdzIiwNCiAgICBUUlVFIH4gIk5vIERhdGEiDQogICksLmJlZm9yZSA9IHBvc2l0aXZlX3JhdGluZ3MpICU+JSANCiAgc2VsZWN0KC1wZXJjZW50X3Bvc2l0aXZlX3Jldmlld3MpDQpgYGANCg0KDQoNCmBgYHtyfQ0KYmFja2xvZ2dkIDwtIHJlYWRfY3N2KCJjbGVhbl9kYXRhL2JhY2tsb2dnZF9jbGVhbi5jc3YiKQ0KYGBgDQoNCmBgYHtyfQ0KYmFja2xvZ2dkDQpgYGANCg0KDQpgYGB7cn0NCmdhbWVzX3JhdyA8LSBnYW1lc19yYXcgJT4lIA0KICBjbGVhbl9uYW1lcygpDQpgYGANCg0KYGBge3J9DQojIFBsYXRmb3JtIGlzbid0IGEgZ2VucmUgLSBjb3JyZWN0aW5nDQpnYW1lc19yYXcgPC0gZ2FtZXNfcmF3ICU+JSANCiAgbXV0YXRlKGdlbnJlID0gY2FzZV93aGVuKA0KICAgIGdlbnJlID09ICJQbGF0Zm9ybSIgfiAiUGxhdGZvcm1lciIsDQogICAgVFJVRSB+IGdlbnJlDQogICkpDQpgYGANCg0KYGBge3J9DQpuaW50ZW5kb19wdWJsaXNoZWQgPC0gZ2FtZXNfcmF3ICU+JSANCiAgZmlsdGVyKHB1Ymxpc2hlciA9PSAiTmludGVuZG8iKQ0KYGBgDQoNCmBgYHtyfQ0KZ2VucmVfcHVibGlzaGVyX3NhbGVzIDwtIGdhbWVzX3JhdyAlPiUgIA0KICBncm91cF9ieShwdWJsaXNoZXIsIGdlbnJlKSAlPiUgDQogIHN1bW1hcmlzZShzdW0oZ2xvYmFsX3NhbGVzKSkgJT4lIA0KICBhcnJhbmdlKGRlc2MoYHN1bShnbG9iYWxfc2FsZXMpYCkpDQpgYGANCmBgYHtyfQ0Kd3JpdGVfY3N2KGdlbnJlX3B1Ymxpc2hlcl9zYWxlcywgImNsZWFuX2RhdGEvZ2VucmVfYnlfcHVibGlzaGVyLmNzdiIpDQpgYGANCg0KYGBge3J9DQpnZW5yZV9wdWJsaXNoZXJfc2FsZXMgJT4lIA0KICBmaWx0ZXIocHVibGlzaGVyID09ICJGcm9tIFNvZnR3YXJlIikNCmBgYA0KDQpgYGB7cn0NCmdhbWVzX3JhdyAlPiUgDQogIGRpc3RpbmN0KHJhdGluZykNCmBgYA0KDQoNCmBgYHtyfQ0KIyBjbGFyaWZ5aW5nIHRoYXQgdGhlIHJhdGluZyBpcyBmb3IgRVNSUCAtIHRoZSBhbWVyaWNhbiBzeXN0ZW0NCmdhbWVzX3JhdyA8LSBnYW1lc19yYXcgJT4lIA0KICByZW5hbWUoImVzcnAiID0gInJhdGluZyIpIA0KYGBgDQoNCmBgYHtyfQ0KIyBBZGRpbmcgUEVHSSBlcXVpdmFsZW50IA0KZ2FtZXNfcmF3IDwtIGdhbWVzX3JhdyAlPiUgDQogIG11dGF0ZShwZWdpX2VxdWl2YWxlbnQgPSBjYXNlX3doZW4oDQogICAgZXNycCA9PSAiRUMiIH4gIjMiLA0KICAgIGVzcnAgPT0gIkUiIH4gIjciLA0KICAgIGVzcnAgPT0gIkUxMCsiIH4gIjEyIiwNCiAgICBlc3JwID09ICJUIiB+ICIxNiIsDQogICAgZXNycCA9PSAiTSIgfiAiMTgiLA0KICAgIGVzcnAgPT0gIkFPIiB+ICIxOCIsDQogICAgZXNycCA9PSAiSy1BIiB+ICI3IiwNCiAgICBlc3JwID09ICJSUCIgfiAiTm8gUmF0aW5nIiwNCiAgICBUUlVFIH4gIk5vIFJhdGluZyBGb3VuZCINCiAgKSkgDQogIA0KYGBgDQoNCmBgYHtyfQ0KdG90YWxfc2FsZXNfYnlfZ2VucmUgPC0gZ2FtZXNfcmF3ICU+JSANCiAgZ3JvdXBfYnkoZ2VucmUpICU+JSANCiAgc3VtbWFyaXNlKHN1bShnbG9iYWxfc2FsZXMpKSAlPiUgDQogIHJlbmFtZSgidG90YWxfc2FsZXMiID0gInN1bShnbG9iYWxfc2FsZXMpIikgJT4lIA0KICBhcnJhbmdlKGRlc2ModG90YWxfc2FsZXMpKQ0KYGBgDQoNCmBgYHtyfQ0KdG90YWxfc2FsZXNfYnlfZ2VucmUgPC0gdG90YWxfc2FsZXNfYnlfZ2VucmUgJT4lIA0KICBkcm9wX25hKCkNCmBgYA0KDQpgYGB7cn0NCmdhbWVzX3JhdyANCmBgYA0KDQpgYGB7cn0NCmJyZWFrZG93bl9zYWxlc19ieV9nZW5yZSA8LSBnYW1lc19yYXcgJT4lIA0KICBncm91cF9ieShnZW5yZSkgJT4lIA0KICBzdW1tYXJpc2Uoc3VtKG5hX3NhbGVzKSwgc3VtKGV1X3NhbGVzKSwgc3VtKGpwX3NhbGVzKSwgc3VtKG90aGVyX3NhbGVzKSkgJT4lIA0KICByZW5hbWUoInRvdGFsX25hX3NhbGVzIj0gInN1bShuYV9zYWxlcykiLCAidG90YWxfZXVfc2FsZXMiID0gInN1bShldV9zYWxlcykiLCAidG90YWxfanBfc2FsZXMiID0gInN1bShqcF9zYWxlcykiLCAidG90YWxfb3RoZXJfc2FsZXMiID0gInN1bShvdGhlcl9zYWxlcykiKQ0KYGBgDQoNCmBgYHtyfQ0KdG90YWxfc2FsZXNfYnlfZ2VucmUgIyB0aGlzIHNlZW1zIHRvIGhhdmUgc29tZSByb3VuZGluZyBkaWZmZXJlbmNlcyBjb21wYXJlZCB0byBicmVha2Rvd24sIHNvIGknbGwgcmV0aXJlIHRoaXMgb25lIA0KYGBgDQpob3cgZG9lcyB0aGUgc2FsZXMgZm9yIHRoZSB0b3AgMyBnZW5yZXMgbG9vayBpbiBlYWNoIHJlZ2lvbj8NCg0KDQpgYGB7cn0NCmJyZWFrZG93bl9zYWxlc19ieV9nZW5yZSA8LSBicmVha2Rvd25fc2FsZXNfYnlfZ2VucmUgJT4lIA0KICBncm91cF9ieShnZW5yZSkgJT4lIA0KICBtdXRhdGUodG90YWxfc2FsZXMgPSBzdW0odG90YWxfbmFfc2FsZXMgKyB0b3RhbF9ldV9zYWxlcyArIHRvdGFsX2pwX3NhbGVzICsgdG90YWxfb3RoZXJfc2FsZXMpKSAlPiUgDQogIGRyb3BfbmEoKQ0KYGBgDQpgYGB7cn0NCg0KYnJlYWtkb3duX3NhbGVzX2J5X2dlbnJlICU+JSANCiAgZmlsdGVyKGdlbnJlICVpbiUgYygiQWN0aW9uIiwgIlNwb3J0cyIsICJTaG9vdGVyIikpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gdG90YWxfc2FsZXMsIHkgPSBnZW5yZSkpKw0KICBnZW9tX2NvbCgpICsNCiAgZ2VvbV9jb2woYWVzKHggPSB0b3RhbF9uYV9zYWxlcyksIGZpbGwgPSAiZ3JlZW4iKSsNCiAgZ2VvbV9jb2woYWVzKHggPSB0b3RhbF9ldV9zYWxlcyksIGZpbGwgPSAicmVkIikgKw0KICBnZW9tX2NvbChhZXMoeCA9IHRvdGFsX2pwX3NhbGVzKSwgZmlsbCA9ICJibHVlIikgDQoNCiMgdGhpcyBsb29rcyBzaGl0DQpgYGANCg0KV2hhdCBhYm91dCB0cmVuZHM/IEhvdyBkaWQgZWFjaCBnZW5yZXMgc2FsZXMgYWRqdXN0IGV2ZXJ5IDUgb3Igc28geWVhcnM/DQoNCmBgYHtyfQ0KZ2FtZXNfcmF3ICU+JSANCiAgZmlsdGVyKHllYXJfb2ZfcmVsZWFzZSA9PSAiMjAxNiIpDQoNCmdhbWVzX3JhdyAlPiUgDQogIG11dGF0ZSh5ZWFyX29mX3JlbGVhc2UgPSBhcy5pbnRlZ2VyKHllYXJfb2ZfcmVsZWFzZSkpICU+JSANCiAgZGlzdGluY3QoeWVhcl9vZl9yZWxlYXNlKSAlPiUgDQogIGFycmFuZ2UoeWVhcl9vZl9yZWxlYXNlKQ0KDQpgYGANCg0KYGBge3J9DQpzYWxlc18yMDE5IDwtIHJlYWRfY3N2KCJyYXdfZGF0YS9zYWxlcy0yMDE5LmNzdiIpDQpgYGANCg0KYGBge3J9DQpzYWxlc18yMDE5ICU+JSANCiAgZGlzdGluY3QoWWVhcikgJT4lIA0KICBhcnJhbmdlKGRlc2MoWWVhcikpDQpgYGANCmBgYHtyfQ0Kc2FsZXNfMjAxOSAlPiUgDQogIGZpbHRlcihZZWFyID09ICIyMDE5IikgJT4lIA0KICBzZWxlY3QoTmFtZSwgWWVhciwgUGxhdGZvcm0pDQoNCiMgZGF0YSBmb3IgMjAyMCBpcyB0b3RhbCBub25zZW5zZS4gU29tZSBpbmZvcm1hdGlvbiBpbiAyMDE5IGlzIGluY29ycmVjdC4NCmBgYA0KIyBHb2luZyBvZmYgdGhlIGZhY3QgdGhhdCB0aGVyZSBpcyB0aGUgbWFqb3JpdHkgb2YgdXNhYmxlIGluZm9ybWF0aW9uIGkgYW0gYWJsZSB0byBnZXQgaXMgZnJvbSAyMDE5IG9yIGJlZm9yZSwgd2UncmUganVzdCBnb2luZyB0byBwcmV0ZW5kIHdlJ3JlIGxpdmluZyBpbiBhbiANCiMgYWx0ZXJuYXRpdmUgMjAxOQ0KDQpBcyBzdWNoLCBJIGFtIGRyb3BwaW5nIGFsbCBkYXRhIGZyb20gMjAyMCBpbiB0aGlzIGRhdGFzZXQgDQoNCmBgYHtyfQ0Kc2FsZXNfMjAxOSA8LSBzYWxlc18yMDE5ICU+JSANCiAgZmlsdGVyKFllYXIgIT0gIjIwMjAiKQ0KYGBgDQoNCiMgTG9va2luZyBhdCBiYWNrbG9nZ2QgYWdhaW4NCg0KYGBge3J9DQpiYWNrbG9nZ2QNCmBgYA0KYGBge3J9DQojIGNyZWF0aW5nIGEgcmFuZ2VfcmF0aW5nIGNvbHVtbiB0byByZWR1Y2Ugbm9pc2Ugd2hlbiBpdCBjb21lcyB0byBwbG90dGluZyByZXN1bHRzDQpiYWNrbG9nZ2VkIDwtIGJhY2tsb2dnZCAlPiUgDQogIG11dGF0ZShyYXRpbmdfcmFuZ2UgPSBjYXNlX3doZW4oDQogICAgcmF0aW5nIDwgNSAmIHJhdGluZyA+PSA0IH4gIjQrIiwNCiAgICByYXRpbmcgPCA0ICYgcmF0aW5nID49IDMgfiAiMyB0byA0IiwNCiAgICByYXRpbmcgPCAzICYgcmF0aW5nID49IDIgfiAiMiB0byAzIiwNCiAgICByYXRpbmcgPCAyICYgcmF0aW5nID49IDEgfiAiMSB0byAyIiwNCiAgICByYXRpbmcgPCAxIH4gIj4xIiwNCiAgICBUUlVFIH4gIk5vIHJhdGluZyINCiAgKSkNCmBgYA0KDQojIyBESUZGSUNVTFRJRVMgV0lUSCBUSEUgREFUQQ0KDQpBZnRlciBoYXZpbmcgbGl0dGxlIHN1Y2Nlc3MgYXR0ZW1wdGluZyB0byBnZXQgYSBtb3JlIHVwIHRvIGRhdGUgZGF0YSBzZXQsIGkndmUgZGVjaWRlZCB0byBzdGljayB3aXRoIHdoYXQgSSBhbHJlYWR5IGhhdmUgLSBHaXZlbiBtb3JlIHRpbWUsIGkgd291bGQgaGF2ZSBsaWtlZA0KdG8gaGF2ZSBydW4gdGhlIHN0ZWFtL3N0ZWFtIHNweSBzY3JpcHQgdG8gc2NyYXBlIGFsbCB0aGUgc3RlYW0gZGF0YSwgYnV0IHVuZm9ydHVuYXRlbHkgaSBjb3VsZG4ndCBjb21taXQgMyBkYXlzIHRvIGl0Lg0KVGhlcmUgZG9lc24ndCBzZWVtIHRvIGJlIG11Y2ggaW4gdGhlIHdheSBvZiBtb2Rlcm4gc2FsZXMgZGF0YSwgd2l0aCBtb3N0IGNvbXBhbmllcyBub3QgcmVsZWFzaW5nIGZpZ3VyZXMgdW5sZXNzIGl0cyB0byBkbyB3aXRoIGEgbWlsZXN0b25lLg0KR2VucmVzIGFyZSBxdWl0ZSB2YWd1ZSAtIFdoaWxlIGl0IHdvdWxkIGJlIG5pY2UgdG8gaGF2ZSB0YWdzIGxpa2UgIk9wZW4gV29ybGQiLCAiUm91Z2UtbGlrZS9saXRlIiwgd2UgaW5zdGVhZCBtb3N0bHkgaGF2ZSAiQWN0aW9uIiAiQWR2ZW50dXJlIiwgIkluZGllIiwgd2hpY2gNCmFyZSBub3QgaHVnZWx5IGRlc2NyaXB0aXZlLiBUaGlzIG1pZ2h0IG1ha2UgcmVjb21tZW5kaW5nIGEgZ2VucmUgdG8gd29yayBvbiBoYXJkZXINCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIERBWSAzDQoNCmBgYHtyfQ0Kc2FsZXNfMjAxOSAlPiUgDQogIHN1bW1hcnkoKQ0KYGBgDQpBbGwgb2YgdGhlIFZHY2hhcnR6IHNjb3JlcyBhcmUgZW1wdHksIHNvIGl0IGNhbiBnby4gQWxzbywgc2FtZSBhcyBhYm92ZSwgdGhlcmUncyBubyBzdWNoIGdlbnJlIGFzIFBsYXRmb3JtDQoNCmBgYHtyfQ0Kc2FsZXNfMjAxOSA8LSBzYWxlc18yMDE5ICU+JSANCiAgY2xlYW5fbmFtZXMoKSAlPiUgDQogIHNlbGVjdCgtdmdfY2hhcnR6X3Njb3JlKSAlPiUgDQogIG11dGF0ZShnZW5yZSA9IGNhc2Vfd2hlbigNCiAgICBnZW5yZSA9PSAiUGxhdGZvcm0iIH4gIlBsYXRmb3JtZXIiLA0KICAgIFRSVUUgfiBnZW5yZQ0KICApKQ0KICANCmBgYA0KDQpgYGB7cn0NCmdhbWVzX3Jhdw0KYGBgDQoNCmBgYHtyfQ0Kc2FsZXNfMjAxOSAlPiUgDQogIGdyb3VwX2J5KG5hbWUpICU+JSANCiAgc3VtbWFyaXNlKHN1bSh0b3RhbF9zaGlwcGVkKSkgJT4lIA0KICBhcnJhbmdlKGRlc2MoYHN1bSh0b3RhbF9zaGlwcGVkKWApKSANCg0KIyB0b3RhbCBzaGlwcGVkIG1pZ2h0IG5vdCBiZSB0aGUgYmVzdCBtZXRyaWMgZm9yIHNhbGVzLCBidXQgYmV0dGVyIHRoYW4gbm90aGluZw0KYGBgDQoNCmBgYHtyfQ0Kc2FsZXNfMjAxOSAlPiUgDQogIGRpc3RpbmN0KHllYXIpICU+JSANCiAgYXJyYW5nZShkZXNjKHllYXIpKQ0KYGBgDQpgYGB7cn0NCnNhbGVzXzIwMTkgPC0gc2FsZXNfMjAxOSAlPiUgDQogIGZpbHRlcih5ZWFyICE9IDE5NzApDQpgYGANCg0KMTk3MCBpcyBub25zZW5zZS4gZHJvcHBpbmcgZW50aXJlIHllYXINCg0KYGBge3J9DQojIGFkZGluZyBjb2x1bW4gdG8gdXNlIGZvciBzaG93aW5nIHRyZW5kcyBvdmVyIHRpbWUNCnNhbGVzXzIwMTkgPC0gc2FsZXNfMjAxOSAlPiUgDQogIG11dGF0ZShmaXZlX3llYXJfcGVyaW9kID0gY2FzZV93aGVuKA0KICAgIHllYXIgPD0gMjAxOSAmIHllYXIgPj0gMjAxNCB+ICIyMDE0IC0gMjAxOSIsDQogICAgeWVhciA8PSAyMDEzICYgeWVhciA+PSAyMDA4IH4gIjIwMDggLSAyMDEzIiwNCiAgICB5ZWFyIDw9IDIwMDcgJiB5ZWFyID49IDIwMDIgfiAiMjAwMiAtIDIwMDciLA0KICAgIHllYXIgPD0gMjAwMSAmIHllYXIgPj0gMTk5NiB+ICIxOTk2IC0gMjAwMSIsDQogICAgeWVhciA8PSAxOTk1ICYgeWVhciA+PSAxOTkxIH4gIjE5OTEgLSAxOTk1IiwNCiAgICB5ZWFyIDw9IDE5OTAgJiB5ZWFyID49IDE5ODUgfiAiMTk4NSAtIDE5OTAiLA0KICAgIHllYXIgPD0gMTk4NCAmIHllYXIgPj0gMTk4MSB+ICIxOTgxIC0gMTk4NCIsDQogICAgeWVhciA8IDE5ODEgfiAiMTk4MCBhbmQgYmVmb3JlIiwNCiAgICBUUlVFIH4gInRoaXMgc2hvdWxkbnQgYXBwZWFyIg0KICApLCAuYWZ0ZXIgPSB5ZWFyKQ0KYGBgDQoNCmBgYHtyfQ0Kc2FsZXNfMjAxOSAlPiUgDQogIGdyb3VwX2J5KGZpdmVfeWVhcl9wZXJpb2QpICU+JSANCiAgY291bnQoZ2VucmUpICU+JSANCiAgc2xpY2VfbWF4KG4gPSAyLCBuKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IGZpdmVfeWVhcl9wZXJpb2QsIHkgPSBuLCBmaWxsID0gZ2VucmUpKSArDQogIGdlb21fY29sKGNvbG91ciA9ICJibGFjayIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJNb3N0IENvbW1vbiBHZW5yZXMgT3ZlciBUaW1lIiwNCiAgICBzdWJ0aXRsZSA9ICJTaG93biBvdmVyIDUgeWVhciBpbnRlcnZhbHMiLA0KICAgIGNhcHRpb24gPSAiRnJvbSAyMDE5IGdhbWVzIHNhbGVzIGRhdGEiDQogICkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKA0KICAgICJQbGF0Zm9ybWVyIiA9ICIjMDRFNzYyIiwNCiAgICAiQWN0aW9uIiA9ICIjREMwMDczIiwNCiAgICAiU3BvcnRzIiA9ICIjMDA4QkY4IiwNCiAgICAiTWlzYyIgPSAiI2Y1YjcwMCIsDQogICAgIlNob290ZXIiID0gIiMzOTAwOTkiDQogICkpICsNCiAgdGhlbWVfbGlnaHQoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMjUsIGhqdXN0ID0gMC41LCBzaXplID0gOSwgZmFjZSA9ICJib2xkIiwgdmp1c3QgPSAwLjgpKSArDQogIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSkrDQogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LCBmYWNlID0gImJvbGQiKSkgKw0KICB4bGFiKCJJbnRlcnZhbCIpICsNCiAgeWxhYigiTnVtYmVyIG9mIEdhbWVzIGluIHRoZSBnZW5yZSByZWxlYXNlZCIpICsNCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiaXRhbGljIiwgc2l6ZSA9IDEwKSkgKw0KICB0aGVtZShheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJpdGFsaWMiLCBzaXplID0gMTApKSArDQogIHRoZW1lKHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChzaXplID0gNywgaGp1c3QgPSAxLjI1KSkgKw0KICBsYWJzKGZpbGwgPSAiR2VucmUiKQ0KDQojIE1pc2MgaXNudCB2ZXJ5IGRlc2NyaXB0aXZlIG9yIGhlbHBmdWwgLSBpbiB0ZXJtcyBvZiByZWNvbW1lbmRpbmcgbWFraW5nIHNvbWV0aGluZyB0byBzb21lb25lIGl0IG1lYW5zIGVzc2VudGlhbGx5ICJ0cnkgYW55dGhpbmciDQpgYGANCg0KYGBge3J9DQoNCiMgUExPVCBTSE9XSU5HIE1PU1QgQ09NTU9OIEdFTlJFIE9GIEdBTUVTIC0gTk9UIE5FQ0VTU0FSSUxZIEJFU1QgU0VMTElORw0Kc2FsZXNfMjAxOSAlPiUgDQogIGdyb3VwX2J5KGZpdmVfeWVhcl9wZXJpb2QpICU+JSANCiAgZmlsdGVyKGdlbnJlICE9ICJNaXNjIikgJT4lIA0KICBjb3VudChnZW5yZSkgJT4lIA0KICBzbGljZV9tYXgobiA9IDIsIG4pICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gZml2ZV95ZWFyX3BlcmlvZCwgeSA9IG4sIGZpbGwgPSBnZW5yZSkpICsNCiAgZ2VvbV9jb2woY29sb3VyID0gImJsYWNrIikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIk1vc3QgQ29tbW9uIEdlbnJlcyBPdmVyIFRpbWUiLA0KICAgIHN1YnRpdGxlID0gIlNob3duIG92ZXIgNSB5ZWFyIGludGVydmFscyAtIEV4Y2x1ZGluZyAnTWlzYycgZ2VucmUiLA0KICAgIGNhcHRpb24gPSAiRnJvbSAyMDE5IGdhbWUgc2FsZXMgZGF0YSINCiAgKSArDQogICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKA0KICAgIlBsYXRmb3JtZXIiID0gIiMwNEU3NjIiLA0KICAgICJBY3Rpb24iID0gIiNEQzAwNzMiLA0KICAgICJTcG9ydHMiID0gIiMwMDhCRjgiLA0KICAgIyAiTWlzYyIgPSAiI2Y1YjcwMCIsDQogICAgIlNob290ZXIiID0gIiMzOTAwOTkiLA0KICAgICJBZHZlbnR1cmUiID0gIiM4YWM5MjYiLA0KICAgICJSb2xlLVBsYXlpbmciID0gIiNmZjZiMzUiDQogICApKSArDQogIHRoZW1lX2xpZ2h0KCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI1LCBoanVzdCA9IDAuNSwgc2l6ZSA9IDksIGZhY2UgPSAiYm9sZCIsIHZqdXN0ID0gMC44KSkgKw0KICB0aGVtZShheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIikpKw0KICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSwgZmFjZSA9ICJib2xkIikpICsNCiAgeGxhYigiSW50ZXJ2YWwiKSArDQogIHlsYWIoIk51bWJlciBvZiBHYW1lcyBpbiB0aGUgZ2VucmUgcmVsZWFzZWQiKSArDQogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChmYWNlID0gIml0YWxpYyIsIHNpemUgPSAxMCkpICsNCiAgdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiaXRhbGljIiwgc2l6ZSA9IDEwKSkgKw0KICB0aGVtZShwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcsIGhqdXN0ID0gMS4yNSkpICsNCiAgbGFicyhmaWxsID0gIkdlbnJlIikNCiAgICAgICAgIA0KYGBgDQoNCmBgYHtyfQ0Kc2FsZXNfMjAxOSAlPiUgDQogIGZpbHRlcihmaXZlX3llYXJfcGVyaW9kID09ICIyMDE5IC0gMjAxNCIpICU+JSANCiAgZmlsdGVyKGdlbnJlID09ICJNaXNjIikNCmBgYA0KVGhpcyBpcyBzbGlnaHRseSBjb25jZXJuaW5nIC0gYSBsb3Qgb2YgdGhlc2UgdGl0bGVzIGNvdWxkIGVhc2lseSBoYXZlIGEgZ2VucmUgdGhhdCBpc24ndCB0aGUgY3VyZS1hbGwgIk1pc2MiIC0gDQpJbmNsdWRlIGJvdGggZ3JhcGhzIC0gb25lIHdpdGggbWlzYywgb25lIGV4Y2x1ZGluZyBpdA0KDQpgYGB7cn0NCmdhbWVzX3JhdyAlPiUgDQogIGZpbHRlcihnZW5yZSA9PSAiTWlzYyIpDQpgYGANCldoYXQgYWJvdXQgYSBzaW1pbGFyIHBsb3QgZm9yIHN0ZWFtIGdhbWVzPw0KDQpgYGB7cn0NCnN0ZWFtDQpgYGANCmBgYHtyfQ0Kc3RlYW1feWVhcnMgPC0gc3RlYW0gJT4lIA0KICBtdXRhdGUocmVsZWFzZV95ZWFyID0geWVhcihyZWxlYXNlX2RhdGUpLC5hZnRlciA9IHJlbGVhc2VfZGF0ZSkNCmBgYA0KYGBge3J9DQpzdGVhbV95ZWFycyAlPiUgDQogIG11dGF0ZShsZW5ndGhfZ2VucmUgPSBuY2hhcihnZW5yZXMpLC5hZnRlciA9IG5hbWUpICU+JSANCiAgYXJyYW5nZShkZXNjKGxlbmd0aF9nZW5yZSkpDQpgYGANCg0KYGBge3J9DQpzdGVhbV95ZWFycyAlPiUgDQogIGRpc3RpbmN0KHJlbGVhc2VfeWVhcikgJT4lIA0KICBhcnJhbmdlKGRlc2MocmVsZWFzZV95ZWFyKSkNCmBgYA0KYGBge3J9DQpzdGVhbV95ZWFycyA8LSBzdGVhbV95ZWFycyAlPiUgIA0KICBzZXBhcmF0ZShjb2wgPSBnZW5yZXMsIHNlcCA9ICI7IiwgaW50byA9IHBhc3RlMCgiR2VucmUiLCBzZXFfbGVuKG1heChuY2hhciguJGdlbnJlcykpKSkpICU+JSAgIyB0aGlzIGlzIGFic29sdXRlbHkgaG9ycmVuZG91cywgYnV0IGl0IGdldHMgbWUgYWxsIHRoZSBnZW5yZXMgaW50byBzZXBhcmF0ZSBjb2x1bW5zIHNvIHdoYXRldmVyDQogIHNlbGVjdCgtR2VucmUxNDotR2VucmUxODApICU+JSANCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBHZW5yZTE6R2VucmUxMywgbmFtZXNfdG8gPSAiZ2VucmVzIikgJT4lIA0KICBkcm9wX25hKHZhbHVlKSAlPiUgIyBvayBub3cgd2UgY2FuIG1ha2UgdGhlIHllYXIgaW50ZXJ2YWxzIGFuZCBncm91cCB0aGVtIHRvIGZpbmQgd2hhdCBnZW5yZXMgd2VyZSBwb3B1bGFyIA0KICBtdXRhdGUoeWVhcl9yYW5nZSA9IGNhc2Vfd2hlbigNCiAgICByZWxlYXNlX3llYXIgPD0gMjAxOSAmIHJlbGVhc2VfeWVhciA+PSAyMDE2IH4gIjIwMTYgLSAyMDE5IiwNCiAgICByZWxlYXNlX3llYXIgPD0gMjAxNSAmIHJlbGVhc2VfeWVhciA+PSAyMDEyIH4gIjIwMTIgLSAyMDE1IiwNCiAgICByZWxlYXNlX3llYXIgPD0gMjAxMSAmIHJlbGVhc2VfeWVhciA+PSAyMDA5IH4gIjIwMDkgLSAyMDExIiwNCiAgICByZWxlYXNlX3llYXIgPD0gMjAwOCAmIHJlbGVhc2VfeWVhciA+PSAyMDA1IH4gIjIwMDUgLSAyMDA4IiwNCiAgICByZWxlYXNlX3llYXIgPD0gMjAwNCAmIHJlbGVhc2VfeWVhcj49IDIwMDAgfiAiMjAwMCAtIDIwMDQiLA0KICAgIHJlbGVhc2VfeWVhciA8IDIwMDEgfiAiQmVmb3JlIDIwMDAiLA0KICAgIFRSVUUgfiAidGhpcyBzaG91bGRudCBhcHBlYXIiDQogICksLmFmdGVyID0gcmVsZWFzZV95ZWFyKSANCmBgYA0KDQpgYGB7cn0NCnN0ZWFtX3llYXJzICU+JSANCiAgZmlsdGVyKHllYXJfcmFuZ2UgPT0gIjIwMDAgLSAyMDA0IikNCmBgYA0KYGBge3J9DQpzdGVhbV95ZWFycyAlPiUgDQogIGdyb3VwX2J5KHllYXJfcmFuZ2UpICU+JSANCiAgY291bnQodmFsdWUpICU+JSANCiAgc2xpY2VfbWF4KG4gPSAyLCBuKSAlPiUgDQogIGFycmFuZ2UoZGVzYyhuKSkgICU+JSANCiAgZmlsdGVyKHllYXJfcmFuZ2UgIT0gIkJlZm9yZSAyMDAwIikgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSB5ZWFyX3JhbmdlLCB5ID0gbiwgZmlsbCA9IHZhbHVlKSkgKw0KICBnZW9tX2NvbChjb2xvdXIgPSAiYmxhY2siKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiTW9zdCBDb21tb24gR2VucmVzIE92ZXIgVGltZSIsDQogICAgc3VidGl0bGUgPSAiU2hvd24gb3ZlciAzLTQgeWVhciBpbnRlcnZhbHMiLA0KICAgIGNhcHRpb24gPSAiRnJvbSAyMDE5IFN0ZWFtL1N0ZWFtIFNweSBkYXRhIg0KICApICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygNCiAgICAiSW5kaWUiID0gIiMwNEU3NjIiLA0KICAgICJBY3Rpb24iID0gIiNEQzAwNzMiDQogICkpICsNCiAgdGhlbWVfbGlnaHQoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMjUsIGhqdXN0ID0gMC41LCBzaXplID0gOSwgZmFjZSA9ICJib2xkIiwgdmp1c3QgPSAwLjgpKSArDQogIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSkrDQogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LCBmYWNlID0gImJvbGQiKSkgKw0KICB4bGFiKCJJbnRlcnZhbCIpICsNCiAgeWxhYigiTnVtYmVyIG9mIEdhbWVzIGluIHRoZSBnZW5yZSByZWxlYXNlZCIpICsNCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiaXRhbGljIiwgc2l6ZSA9IDEwKSkgKw0KICB0aGVtZShheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJpdGFsaWMiLCBzaXplID0gMTApKSArDQogIHRoZW1lKHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChzaXplID0gNywgaGp1c3QgPSAxLjI1KSkgKw0KICBsYWJzKGZpbGwgPSAiR2VucmUiKQ0KYGBgDQoNCmBgYHtyfQ0KIyBIYXBweSB3aXRoIHRoaXMgb25lIGFzIGEgY29tcGFyaXNvbiBwb2ludA0Kc3RlYW1feWVhcnMgJT4lIA0KICBmaWx0ZXIocmVsZWFzZV95ZWFyID49IDIwMDkpICU+JSANCiAgZ3JvdXBfYnkocmVsZWFzZV95ZWFyKSAlPiUgDQogIGNvdW50KHZhbHVlKSAlPiUgDQogIHNsaWNlX21heChuID0gMiwgbikgJT4lIA0KICBhcnJhbmdlKGRlc2MobikpICAlPiUgDQogIGdncGxvdChhZXMoeCA9IHJlbGVhc2VfeWVhciwgeSA9IG4sIGZpbGwgPSB2YWx1ZSkpICsNCiAgZ2VvbV9jb2woY29sb3VyID0gImJsYWNrIikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIk1vc3QgQ29tbW9uIEdlbnJlcyBPdmVyIFRpbWUiLA0KICAgIHN1YnRpdGxlID0gIlNob3duIHllYXIgYnkgeWVhciBmcm9tIDIwMDkgdW50aWwgTWF5IDIwMTkiLA0KICAgIGNhcHRpb24gPSAiRnJvbSAyMDE5IFN0ZWFtL1N0ZWFtIFNweSBkYXRhIg0KICApICsNCiAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoDQogICAgICJJbmRpZSIgPSAiIzA0RTc2MiIsDQogICAgICJBY3Rpb24iID0gIiNEQzAwNzMiLA0KICAgICAiQ2FzdWFsIiA9ICIjMDA4QkY4IiwNCiAgICAgIkFkdmVudHVyZSIgPSAiI2Y1YjcwMCINCiAgICkpICsNCiAgdGhlbWVfbGlnaHQoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMjUsIGhqdXN0ID0gMC41LCBzaXplID0gOSwgZmFjZSA9ICJib2xkIiwgdmp1c3QgPSAwLjgpKSArDQogIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSkrDQogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LCBmYWNlID0gImJvbGQiKSkgKw0KICB4bGFiKCJJbnRlcnZhbCIpICsNCiAgeWxhYigiTnVtYmVyIG9mIEdhbWVzIGluIHRoZSBnZW5yZSByZWxlYXNlZCIpICsNCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiaXRhbGljIiwgc2l6ZSA9IDEwKSkgKw0KICB0aGVtZShheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJpdGFsaWMiLCBzaXplID0gMTApKSArDQogIHRoZW1lKHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChzaXplID0gNywgaGp1c3QgPSAxLjI1KSkgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYygyMDA5LCAyMDEwLCAyMDExLCAyMDEyLCAyMDEzLCAyMDE0LCAyMDE1LCAyMDE2LCAyMDE3LCAyMDE4LCAyMDE5KSkgKw0KICBsYWJzKGZpbGwgPSAiR2VucmUiKQ0KYGBgDQoNCg0KYGBge3J9DQpzdGVhbV95ZWFycyAlPiUgDQogIGZpbHRlcihyZWxlYXNlX3llYXIgPT0gMjAxOSkNCmBgYA0KDQoNCmBgYHtyfQ0Kc3RlYW1feWVhcnMgJT4lIA0KICBtdXRhdGUobW9udGggPSBtb250aChyZWxlYXNlX2RhdGUpKSAlPiUgDQogIGZpbHRlcihyZWxlYXNlX3llYXIgPT0gMjAxOSkgJT4lIA0KICBzZWxlY3QobW9udGgpICU+JSANCiAgYXJyYW5nZShkZXNjKG1vbnRoKSkNCmBgYA0KYGBge3J9DQpiYWNrbG9nZ2QNCmBgYA0KDQpgYGB7cn0NCmJhY2tsb2dnZF9nZW5yZXMgPC0gYmFja2xvZ2dkICU+JSANCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBnZW5yZV90YWc6Z2VucmVfdGFnXzcsIG5hbWVzX3RvID0gImxpc3QiLCB2YWx1ZXNfdG8gPSAiZ2VucmUiKSAlPiUgDQogIGRyb3BfbmEoZ2VucmUpDQpgYGANCg0KYGBge3J9DQojIG9rIG5vdyBpJ3ZlIGRlZmluaXRlbHkgZ290dGVuIHJpZCBvZiBldmVyeXRoaW5nIHRoYXQgaGFzbnQgcmVsZWFzZWQNCmJhY2tsb2dnZF9nZW5yZXMgPC0gYmFja2xvZ2dkX2dlbnJlcyAlPiUgDQogIG11dGF0ZShyZWxlYXNlX3llYXIgPSB5ZWFyKHJlbGVhc2VfZGF0ZSkpICU+JSANCiAgZmlsdGVyKC15ZWFyc19zaW5jZV9yZWxlYXNlIDwgMC4wMSkNCmBgYA0KDQpgYGB7cn0NCmJhY2tsb2dnZF9nZW5yZXMgJT4lIA0KICBkaXN0aW5jdChyZWxlYXNlX3llYXIpICU+JSANCiAgYXJyYW5nZShkZXNjKHJlbGVhc2VfeWVhcikpDQpgYGANCmBgYHtyfQ0KYmFja2xvZ2dkX2dlbnJlcyA8LSBiYWNrbG9nZ2RfZ2VucmVzICU+JSAgIA0KICBtdXRhdGUoaW50ZXJ2YWxzID0gY2FzZV93aGVuKA0KICAgcmVsZWFzZV95ZWFyIDw9IDIwMjMgJiByZWxlYXNlX3llYXIgPj0gMjAyMCB+ICIyMDIwIC0gMjAyMyIsDQogICAgcmVsZWFzZV95ZWFyIDw9IDIwMTkgJiByZWxlYXNlX3llYXIgPj0gMjAxNCB+ICIyMDE0IC0gMjAxOSIsDQogICAgcmVsZWFzZV95ZWFyIDw9IDIwMTMgJiByZWxlYXNlX3llYXIgPj0gMjAwOCB+ICIyMDA4IC0gMjAxMyIsDQogICAgcmVsZWFzZV95ZWFyICA8PSAyMDA3ICYgcmVsZWFzZV95ZWFyICA+PSAyMDAyIH4gIjIwMDIgLSAyMDA3IiwNCiAgICByZWxlYXNlX3llYXIgIDw9IDIwMDEgJiByZWxlYXNlX3llYXIgID49IDE5OTYgfiAiMTk5NiAtIDIwMDEiLA0KICAgIHJlbGVhc2VfeWVhciAgPD0gMTk5NSAmIHJlbGVhc2VfeWVhciAgPj0gMTk5MSB+ICIxOTkxIC0gMTk5NSIsDQogICAgcmVsZWFzZV95ZWFyICA8PSAxOTkwICYgcmVsZWFzZV95ZWFyICA+PSAxOTg1IH4gIjE5ODUgLSAxOTkwIiwNCiAgICByZWxlYXNlX3llYXIgIDw9IDE5ODQgJiByZWxlYXNlX3llYXIgID49IDE5ODEgfiAiMTk4MSAtIDE5ODQiLA0KICAgIHJlbGVhc2VfeWVhciAgPCAxOTgxIH4gIjE5ODAgYW5kIGJlZm9yZSIsDQogICAgVFJVRSB+ICJ0aGlzIHNob3VsZG50IGFwcGVhciINCiAgKSkgDQpgYGANCg0KYGBge3J9DQojIFRoaXMgaXNuJ3Qgc2hvd2luZyB0aGUgbW9zdCBwb3B1bGFyIGdlbnJlcyBpbiBhIHRpbWVmcmFtZSwgbW9yZSBvZiBhbiBpbnNpZ2h0IGludG8gd2hhdCBwZW9wbGUgYXJlIHBsYXlpbmcNCiMgR3JhbnRlZCwgQmFja2xvZ2dkIGlzbid0IHRoZSBiaWdnZXN0IHNlcnZpY2UgaW4gdGhlIHdvcmxkLCBidXQgaXQncyBhIGdvb2QgaWRlYSBvZiB3aGF0IHBlb3BsZSBsaWtlLCBhbmQgc3RpbGwgcGxheQ0KYmFja2xvZ2dkX2dlbnJlcyAlPiUgDQogIG11dGF0ZShnZW5yZSA9IGNhc2Vfd2hlbigNCiAgICBnZW5yZSA9PSAiUGxhdGZvcm0iIH4gIlBsYXRmb3JtZXIiLA0KICAgIFRSVUUgfiBnZW5yZQ0KICApKSAlPiUNCiAgZmlsdGVyKGludGVydmFscyAhPSAiMTk4MCBhbmQgYmVmb3JlIikgJT4lIA0KICBmaWx0ZXIoaW50ZXJ2YWxzICE9ICIxOTgxIC0gMTk4NCIpICU+JSANCiAgZ3JvdXBfYnkoaW50ZXJ2YWxzKSAlPiUgDQogIGNvdW50KGdlbnJlKSAlPiUgDQogIHNsaWNlX21heChuID0gMiwgbikgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBpbnRlcnZhbHMsIHkgPSBuLCBmaWxsID0gZ2VucmUpKSArDQogIGdlb21fY29sKGNvbG91ciA9ICJibGFjayIpICsNCiAgIGxhYnMoDQogICAgIHRpdGxlID0gIldoYXQgZG8gcGVvcGxlIHN0aWxsIHBsYXk/IiwNCiAgICAgc3VidGl0bGUgPSAiU3BsaXQgaW50byBHZW5yZSBhbmQgUmVsZWFzZSBZZWFyIiwNCiAgICAgY2FwdGlvbiA9ICJGcm9tIE1hcmNoIDIwMjMgQmFja2xvZ2dkIGRhdGEiDQogICApICsNCiAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoDQogICAiUGxhdGZvcm1lciIgPSAiIzA0RTc2MiIsDQogICAjIkFjdGlvbiIgPSAiI0RDMDA3MyIsDQogICAjIlNwb3J0cyIgPSAiIzAwOEJGOCIsDQogICAjIk1pc2MiID0gIiNmNWI3MDAiLA0KICAgIlNob290ZXIiID0gIiMzOTAwOTkiLA0KICAgIkFkdmVudHVyZSIgPSAiIzhhYzkyNiIsDQogICAiUlBHIiA9ICIjZmY2YjM1Ig0KICAgKSkgKw0KICAgdGhlbWVfbGlnaHQoKSArDQogICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI1LCBoanVzdCA9IDAuNSwgc2l6ZSA9IDksIGZhY2UgPSAiYm9sZCIsIHZqdXN0ID0gMC44KSkgKw0KICAgdGhlbWUoYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJibGFjayIpKSsNCiAgIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LCBmYWNlID0gImJvbGQiKSkgKw0KICAgeGxhYigiUmVsZWFzZSB3aW5kb3ciKSArDQogICB5bGFiKCJIb3cgbWFueSBwZW9wbGUgaGF2ZSBwbGF5ZWQgIikgKw0KICAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiaXRhbGljIiwgc2l6ZSA9IDEwKSkgKw0KICAgdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiaXRhbGljIiwgc2l6ZSA9IDEwKSkgKw0KICAgdGhlbWUocGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KHNpemUgPSA3LCBoanVzdCA9IDEuMjUpKSArDQogICBsYWJzKGZpbGwgPSAiR2VucmUiKQ0KYGBgDQoNCiMgV2UgaGF2ZSBlc3RhYmxpc2hlZCB0aGF0IEluZGllLCBBY3Rpb24gYW5kIEFkdmVudHVyZSBnYW1lcyBzZWVtIHRvIGJlIHRoZSBtb3N0IHBvcHVsYXIgLSBCdXQgd2hhdCBleGFtcGxlcyBvZiB0aGVzZSBhcmUgdGhlcmU/DQoNCg==